import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CustomerServiceAgent } from './entities/agent.entity';
import { CustomerServiceSession } from './entities/session.entity';
import { CustomerServiceMessage } from './entities/message.entity';
import { CreateSessionDto } from './dto/create-session.dto';
import { CreateMessageDto } from './dto/create-message.dto';
import { AssignAgentDto } from './dto/assign-agent.dto';
import { User } from '../user/user.entity';
import { CustomerServiceGroup } from './entities/group.entity';

@Injectable()
export class CustomerServiceService {
  constructor(
    @InjectRepository(CustomerServiceAgent)
    private readonly agentRepo: Repository<CustomerServiceAgent>,
    @InjectRepository(CustomerServiceSession)
    private readonly sessionRepo: Repository<CustomerServiceSession>,
    @InjectRepository(CustomerServiceMessage)
    private readonly messageRepo: Repository<CustomerServiceMessage>,
    @InjectRepository(User)
    private readonly userRepo: Repository<User>,
    @InjectRepository(CustomerServiceGroup)
    private readonly groupRepo: Repository<CustomerServiceGroup>,
  ) {}

  async createSession(dto: CreateSessionDto) {
    const user = await this.userRepo.findOne({ where: { id: dto.userId } });
    if (!user) throw new NotFoundException('用户不存在');
    let group: CustomerServiceGroup | undefined = undefined;
    if (dto.groupId) {
      group = (await this.groupRepo.findOne({ where: { id: dto.groupId } })) || undefined;
      if (!group) throw new NotFoundException('分组不存在');
    }
    const session = this.sessionRepo.create({ user, group, status: 'open' });
    return this.sessionRepo.save(session);
  }

  async assignAgent(dto: AssignAgentDto) {
    const session = await this.sessionRepo.findOne({ where: { id: dto.sessionId }, relations: ['agent'] });
    if (!session) throw new NotFoundException('会话不存在');
    const agent = await this.agentRepo.findOne({ where: { id: dto.agentId } });
    if (!agent) throw new NotFoundException('客服不存在');
    session.agent = agent;
    session.status = 'pending';
    return this.sessionRepo.save(session);
  }

  async sendMessage(dto: CreateMessageDto) {
    const session = await this.sessionRepo.findOne({ where: { id: dto.sessionId } });
    if (!session) throw new NotFoundException('会话不存在');
    let user: User | undefined = undefined;
    let agent: CustomerServiceAgent | undefined = undefined;
    if (dto.senderType === 'user' && dto.userId) {
      user = (await this.userRepo.findOne({ where: { id: dto.userId } })) || undefined;
      if (!user) throw new NotFoundException('用户不存在');
    }
    if (dto.senderType === 'agent' && dto.agentId) {
      agent = (await this.agentRepo.findOne({ where: { id: dto.agentId } })) || undefined;
      if (!agent) throw new NotFoundException('客服不存在');
    }
    const message = this.messageRepo.create({
      session,
      senderType: dto.senderType,
      user,
      agent,
      content: dto.content,
    });
    return this.messageRepo.save(message);
  }

  async getSessionMessages(sessionId: number) {
    return this.messageRepo.find({ where: { session: { id: sessionId } }, order: { createdAt: 'ASC' } });
  }

  async getUserSessions(userId: number) {
    return this.sessionRepo.find({ where: { user: { id: userId } }, relations: ['agent'], order: { createdAt: 'DESC' } });
  }

  async getAgentSessions(agentId: number) {
    return this.sessionRepo.find({ where: { agent: { id: agentId } }, relations: ['user'], order: { createdAt: 'DESC' } });
  }

  async closeSession(sessionId: number, reason?: string) {
    const session = await this.sessionRepo.findOne({ where: { id: sessionId } });
    if (!session) throw new NotFoundException('会话不存在');
    session.status = 'closed';
    session.closedReason = reason ?? '';
    return this.sessionRepo.save(session);
  }

  async transferSession(sessionId: number, toAgentId: number) {
    const session = await this.sessionRepo.findOne({ where: { id: sessionId } });
    if (!session) throw new NotFoundException('会话不存在');
    session.status = 'transferred';
    session.transferredToAgentId = toAgentId;
    return this.sessionRepo.save(session);
  }

  async rateSession(sessionId: number, rating: number, comment?: string) {
    const session = await this.sessionRepo.findOne({ where: { id: sessionId } });
    if (!session) throw new NotFoundException('会话不存在');
    session.rating = rating;
    session.ratingComment = comment ?? '';
    return this.sessionRepo.save(session);
  }

  async getAgentStats(agentId: number) {
    const total = await this.sessionRepo.count({ where: { agent: { id: agentId } } });
    const closed = await this.sessionRepo.count({ where: { agent: { id: agentId }, status: 'closed' } });
    const avgRating = await this.sessionRepo
      .createQueryBuilder('s')
      .select('AVG(s.rating)', 'avg')
      .where('s.agentId = :agentId', { agentId })
      .getRawOne();
    return {
      totalSessions: total,
      closedSessions: closed,
      avgRating: avgRating.avg || 0,
    };
  }

  public async setAgentOnline(agentId: number, online: boolean) {
    const agent = await this.agentRepo.findOne({ where: { id: agentId } });
    if (!agent) throw new NotFoundException('客服不存在');
    agent.isOnline = online;
    return this.agentRepo.save(agent);
  }

  // 标记消息为已读
  async markMessageRead(messageId: number) {
    const msg = await this.messageRepo.findOne({ where: { id: messageId } });
    if (!msg) throw new NotFoundException('消息不存在');
    msg.isRead = true;
    return this.messageRepo.save(msg);
  }

  // 获取会话未读消息数
  async getSessionUnreadCount(sessionId: number, forAgent: boolean) {
    return this.messageRepo.count({
      where: {
        session: { id: sessionId },
        isRead: false,
        senderType: forAgent ? 'user' : 'agent',
      },
    });
  }

  // 获取用户/客服所有未读消息总数
  async getUserUnreadCount(userId: number) {
    return this.messageRepo.count({ where: { user: { id: userId }, isRead: false, senderType: 'agent' } });
  }
  async getAgentUnreadCount(agentId: number) {
    return this.messageRepo.count({ where: { agent: { id: agentId }, isRead: false, senderType: 'user' } });
  }

  // 客服会话数排行
  async getAgentSessionRank(limit = 10) {
    return this.agentRepo.createQueryBuilder('agent')
      .leftJoin('agent.group', 'group')
      .leftJoin('customer_service_session', 'session', 'session.agentId = agent.id')
      .select(['agent.id', 'agent.name', 'group.name'])
      .addSelect('COUNT(session.id)', 'sessionCount')
      .groupBy('agent.id')
      .addGroupBy('group.name')
      .orderBy('sessionCount', 'DESC')
      .limit(limit)
      .getRawMany();
  }
  // 客服消息数排行
  async getAgentMessageRank(limit = 10) {
    return this.agentRepo.createQueryBuilder('agent')
      .leftJoin('agent.group', 'group')
      .leftJoin('customer_service_message', 'msg', 'msg.agentId = agent.id')
      .select(['agent.id', 'agent.name', 'group.name'])
      .addSelect('COUNT(msg.id)', 'messageCount')
      .groupBy('agent.id')
      .addGroupBy('group.name')
      .orderBy('messageCount', 'DESC')
      .limit(limit)
      .getRawMany();
  }
  // 客服平均评分排行
  async getAgentRatingRank(limit = 10) {
    return this.agentRepo.createQueryBuilder('agent')
      .leftJoin('agent.group', 'group')
      .leftJoin('customer_service_session', 'session', 'session.agentId = agent.id')
      .select(['agent.id', 'agent.name', 'group.name'])
      .addSelect('AVG(session.rating)', 'avgRating')
      .groupBy('agent.id')
      .addGroupBy('group.name')
      .orderBy('avgRating', 'DESC')
      .limit(limit)
      .getRawMany();
  }
} 